import Sortable from "sortablejs";
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
import { type PropType, ref, unref, computed, nextTick, defineComponent, getCurrentInstance } from "vue";
import { delay, cloneDeep, isBoolean, isFunction, getKeyList } from "@pureadmin/utils";

import Fullscreen from "~icons/ri/fullscreen-fill";
import ExitFullscreen from "~icons/ri/fullscreen-exit-fill";
import DragIcon from "@/assets/table-bar/drag.svg?component";
import ExpandIcon from "@/assets/table-bar/expand.svg?component";
import RefreshIcon from "@/assets/table-bar/refresh.svg?component";
import SettingIcon from "@/assets/table-bar/settings.svg?component";
import CollapseIcon from "@/assets/table-bar/collapse.svg?component";

const props = {
    /** 头部最左边的标题 */
    title: {
        type: String,
        default: "列表"
    },
    /** 对于树形表格，如果想启用展开和折叠功能，传入当前表格的ref即可 */
    tableRef: {
        type: Object as PropType<any>
    },
    /** 需要展示的列 */
    columns: {
        type: Array as PropType<TableColumnList>,
        default: () => []
    },
    isExpandAll: {
        type: Boolean,
        default: true
    },
    tableKey: {
        type: [String, Number] as PropType<string | number>,
        default: "0"
    }
};

export default defineComponent({
    name: "PureTableBar",
    props,
    emits: ["refresh", "fullscreen"],
    setup(props, { emit, slots, attrs }) {
        const size = ref("default");
        const loading = ref(false);
        const checkAll = ref(true);
        const isFullscreen = ref(false);
        const isIndeterminate = ref(false);
        const instance = getCurrentInstance()!;
        const isExpandAll = ref(props.isExpandAll);
        const filterColumns = cloneDeep(props?.columns).filter(column =>
            isBoolean(column?.hide) ? !column.hide : !(isFunction(column?.hide) && column?.hide())
        );
        let checkColumnList = getKeyList(cloneDeep(props?.columns), "label");
        const checkedColumns = ref(getKeyList(cloneDeep(filterColumns), "label"));
        const dynamicColumns = ref(cloneDeep(props?.columns));

        const getDropdownItemStyle = computed(() => {
            return s => {
                return {
                    background: s === size.value ? useEpThemeStoreHook().epThemeColor : "",
                    color: s === size.value ? "#fff" : "var(--el-text-color-primary)"
                };
            };
        });

        const iconClass = computed(() => {
            return [
                "text-black",
                "dark:text-white",
                "duration-100",
                "hover:text-primary!",
                "cursor-pointer",
                "outline-hidden"
            ];
        });

        const topClass = computed(() => {
            return [
                "flex",
                "justify-between",
                "pt-[3px]",
                "px-[11px]",
                "border-b-[1px]",
                "border-solid",
                "border-[#dcdfe6]",
                "dark:border-[#303030]"
            ];
        });

        function onReFresh() {
            loading.value = true;
            emit("refresh");
            delay(500).then(() => (loading.value = false));
        }

        function onExpand() {
            isExpandAll.value = !isExpandAll.value;
            toggleRowExpansionAll(props.tableRef.data, isExpandAll.value);
        }

        function onFullscreen() {
            isFullscreen.value = !isFullscreen.value;
            emit("fullscreen", isFullscreen.value);
        }

        function toggleRowExpansionAll(data, isExpansion) {
            data.forEach(item => {
                props.tableRef.toggleRowExpansion(item, isExpansion);
                if (item.children !== undefined && item.children !== null) {
                    toggleRowExpansionAll(item.children, isExpansion);
                }
            });
        }

        function handleCheckAllChange(val: boolean) {
            checkedColumns.value = val ? checkColumnList : [];
            isIndeterminate.value = false;
            dynamicColumns.value.map(column => (val ? (column.hide = false) : (column.hide = true)));
        }

        function handleCheckedColumnsChange(value: string[]) {
            checkedColumns.value = value;
            const checkedCount = value.length;
            checkAll.value = checkedCount === checkColumnList.length;
            isIndeterminate.value = checkedCount > 0 && checkedCount < checkColumnList.length;
        }

        function handleCheckColumnListChange(val: boolean, label: string) {
            dynamicColumns.value.filter(item => item.label === label)[0].hide = !val;
        }

        async function onReset() {
            checkAll.value = true;
            isIndeterminate.value = false;
            dynamicColumns.value = cloneDeep(props?.columns);
            checkColumnList = [];
            checkColumnList = await getKeyList(cloneDeep(props?.columns), "label");
            checkedColumns.value = getKeyList(cloneDeep(filterColumns), "label");
        }

        const dropdown = {
            dropdown: () => (
                <el-dropdown-menu class="translation">
                    <el-dropdown-item
                        style={getDropdownItemStyle.value("large")}
                        onClick={() => (size.value = "large")}
                    >
                        宽松
                    </el-dropdown-item>
                    <el-dropdown-item
                        style={getDropdownItemStyle.value("default")}
                        onClick={() => (size.value = "default")}
                    >
                        默认
                    </el-dropdown-item>
                    <el-dropdown-item
                        style={getDropdownItemStyle.value("small")}
                        onClick={() => (size.value = "small")}
                    >
                        紧凑
                    </el-dropdown-item>
                </el-dropdown-menu>
            )
        };

        /** 列展示拖拽排序 */
        const rowDrop = (event: { preventDefault: () => void }) => {
            event.preventDefault();
            nextTick(() => {
                const wrapper: HTMLElement = (instance?.proxy?.$refs[`GroupRef${unref(props.tableKey)}`] as any).$el
                    .firstElementChild;
                Sortable.create(wrapper, {
                    animation: 300,
                    handle: ".drag-btn",
                    onEnd: ({ newIndex, oldIndex, item }) => {
                        const targetThElem = item;
                        const wrapperElem = targetThElem.parentNode as HTMLElement;
                        const oldColumn = dynamicColumns.value[oldIndex];
                        const newColumn = dynamicColumns.value[newIndex];
                        if (oldColumn?.fixed || newColumn?.fixed) {
                            // 当前列存在fixed属性 则不可拖拽
                            const oldThElem = wrapperElem.children[oldIndex] as HTMLElement;
                            if (newIndex > oldIndex) {
                                wrapperElem.insertBefore(targetThElem, oldThElem);
                            } else {
                                wrapperElem.insertBefore(
                                    targetThElem,
                                    oldThElem ? oldThElem.nextElementSibling : oldThElem
                                );
                            }
                            return;
                        }
                        const currentRow = dynamicColumns.value.splice(oldIndex, 1)[0];
                        dynamicColumns.value.splice(newIndex, 0, currentRow);
                    }
                });
            });
        };

        const isFixedColumn = (label: string) => {
            return dynamicColumns.value.filter(item => item.label === label)[0].fixed ? true : false;
        };

        const rendTippyProps = (content: string) => {
            // https://vue-tippy.netlify.app/props
            return {
                content,
                offset: [0, 18],
                duration: [300, 0],
                followCursor: true,
                hideOnClick: "toggle"
            };
        };

        const reference = {
            reference: () => <SettingIcon class={["w-[16px]", iconClass.value]} v-tippy={rendTippyProps("列设置")} />
        };

        return () => (
            <>
                <div
                    {...attrs}
                    class={[
                        "w-full",
                        "px-2",
                        "pb-2",
                        "bg-bg_color",
                        isFullscreen.value ? ["h-full!", "z-2002", "fixed", "inset-0"] : "mt-2"
                    ]}
                >
                    <div class="flex justify-between w-full h-[60px] p-4">
                        {slots?.title ? slots.title() : <p class="font-bold truncate">{props.title}</p>}
                        <div class="flex items-center justify-around">
                            {slots?.buttons ? <div class="flex mr-4">{slots.buttons()}</div> : null}
                            {props.tableRef?.size ? (
                                <>
                                    <ExpandIcon
                                        class={["w-[16px]", iconClass.value]}
                                        style={{
                                            transform: isExpandAll.value ? "none" : "rotate(-90deg)"
                                        }}
                                        v-tippy={rendTippyProps(isExpandAll.value ? "折叠" : "展开")}
                                        onClick={() => onExpand()}
                                    />
                                    <el-divider direction="vertical" />
                                </>
                            ) : null}
                            <RefreshIcon
                                class={["w-[16px]", iconClass.value, loading.value ? "animate-spin" : ""]}
                                v-tippy={rendTippyProps("刷新")}
                                onClick={() => onReFresh()}
                            />
                            <el-divider direction="vertical" />
                            <el-dropdown v-slots={dropdown} trigger="click" v-tippy={rendTippyProps("密度")}>
                                <CollapseIcon class={["w-[16px]", iconClass.value]} />
                            </el-dropdown>
                            <el-divider direction="vertical" />

                            <el-popover
                                v-slots={reference}
                                placement="bottom-start"
                                popper-style={{ padding: 0 }}
                                width="200"
                                trigger="click"
                            >
                                <div class={[topClass.value]}>
                                    <el-checkbox
                                        class="-mr-1!"
                                        label="列展示"
                                        v-model={checkAll.value}
                                        indeterminate={isIndeterminate.value}
                                        onChange={value => handleCheckAllChange(value)}
                                    />
                                    <el-button type="primary" link onClick={() => onReset()}>
                                        重置
                                    </el-button>
                                </div>

                                <div class="pt-[6px] pl-[11px]">
                                    <el-scrollbar max-height="36vh">
                                        <el-checkbox-group
                                            ref={`GroupRef${unref(props.tableKey)}`}
                                            modelValue={checkedColumns.value}
                                            onChange={value => handleCheckedColumnsChange(value)}
                                        >
                                            <el-space direction="vertical" alignment="flex-start" size={0}>
                                                {checkColumnList.map((item, index) => {
                                                    return (
                                                        <div class="flex items-center">
                                                            <DragIcon
                                                                class={[
                                                                    "drag-btn w-[16px] mr-2",
                                                                    isFixedColumn(item)
                                                                        ? "cursor-no-drop!"
                                                                        : "cursor-grab!"
                                                                ]}
                                                                onMouseenter={(event: { preventDefault: () => void }) =>
                                                                    rowDrop(event)
                                                                }
                                                            />
                                                            <el-checkbox
                                                                key={index}
                                                                label={item}
                                                                value={item}
                                                                onChange={value =>
                                                                    handleCheckColumnListChange(value, item)
                                                                }
                                                            >
                                                                <span
                                                                    title={item}
                                                                    class="inline-block w-[120px] truncate hover:text-text_color_primary"
                                                                >
                                                                    {item}
                                                                </span>
                                                            </el-checkbox>
                                                        </div>
                                                    );
                                                })}
                                            </el-space>
                                        </el-checkbox-group>
                                    </el-scrollbar>
                                </div>
                            </el-popover>
                            <el-divider direction="vertical" />

                            <iconifyIconOffline
                                class={["w-[16px]", iconClass.value]}
                                icon={isFullscreen.value ? ExitFullscreen : Fullscreen}
                                v-tippy={isFullscreen.value ? "退出全屏" : "全屏"}
                                onClick={() => onFullscreen()}
                            />
                        </div>
                    </div>
                    {slots.default({
                        size: size.value,
                        dynamicColumns: dynamicColumns.value
                    })}
                </div>
            </>
        );
    }
});
